<template>
  <div class="super-date-picker">
    <el-popover
      ref="popoverRef"
      placement="bottom"
      width="auto"
      :visible="visible"
      :popper-style="{
        padding: '0px',
      }"
    >
      <template #reference>
        <div class="super-date-picker-input">
          <el-input
            prefix-icon="calendar"
            :model-value="dateText"
            :clearable="true"
            @clear="onInputClearHandler"
            @click="onInputClickHandler"
          ></el-input>
        </div>
      </template>
      <div class="popper-content" ref="popoverContentRef">
        <div class="body">
          <div class="quick-select">
            <div class="quick-select__title">快速选择</div>
            <div class="quick-select__content">
              <el-row :gutter="8">
                <el-col
                  :span="12"
                  v-for="(item, index) in quickSelectList"
                  :key="index"
                >
                  <div
                    class="quick-select__item"
                    @click="onQuickSelectClickHandler(item)"
                  >
                    {{ item.label }}
                  </div>
                </el-col>
              </el-row>
              <div
                v-if="quickSelectList.length === 0"
                class="quick-select__empty"
              >
                无
              </div>
            </div>
          </div>
          <div class="date-panel">
            <div class="date-panel__tabs">
              <el-tabs v-model="activeName">
                <el-tab-pane name="static">
                  <template #label>
                    <div class="date-panel__tabs-label">
                      <div class="date-panel__tabs-label-text">静态时间</div>
                      <el-tooltip
                        effect="dark"
                        content="静态时间提示"
                        placement="bottom"
                        ><el-icon><question-filled /></el-icon
                      ></el-tooltip>
                    </div>
                  </template>
                </el-tab-pane>
                <el-tab-pane name="dynamic">
                  <template #label>
                    <div class="date-panel__tabs-label">
                      <div class="date-panel__tabs-label-text">动态时间</div>
                      <el-tooltip
                        effect="dark"
                        content="动态时间提示"
                        placement="bottom"
                        ><el-icon><question-filled /></el-icon
                      ></el-tooltip>
                    </div>
                  </template>
                </el-tab-pane>
              </el-tabs>
            </div>
            <div class="date-panel__content">
              <template v-if="activeName === 'static'">
                <picker-panel
                  v-if="!rangeMode"
                  :init-date="dateValue"
                  ref="pickerPanelRef"
                ></picker-panel>
                <range-picker-panel
                  v-else
                  :init-date="dateValue"
                  ref="rangePickerPanelRef"
                ></range-picker-panel>
              </template>
              <template v-if="activeName === 'dynamic'">
                <dynamic-panel
                  v-if="!rangeMode"
                  :init-date="dateValue"
                  ref="dynamicPanelRef"
                ></dynamic-panel>
                <dynamic-range-panel
                  v-else
                  :init-date="dateValue"
                  ref="dynamicRangePanelRef"
                ></dynamic-range-panel>
              </template>
            </div>
          </div>
        </div>
        <div class="footer">
          <el-space>
            <el-button size="small" @click="hide">取消</el-button>
            <el-button
              type="primary"
              size="small"
              @click="onConfirmClickHandler"
              >确定</el-button
            >
          </el-space>
        </div>
      </div>
    </el-popover>
  </div>
</template>

<script setup>
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import dayjs from 'dayjs'
import PickerPanel from './picker-panel.vue'
import RangePickerPanel from './range-picker-panel.vue'
import DynamicPanel from './dynamic-panel.vue'
import DynamicRangePanel from './dynamic-range-panel.vue'
import { isDate, isObject, isString, isArray } from 'lodash-es'

const props = defineProps({
  modelValue: {
    type: [String, Date, Object, Array],
    default: null,
  },
  rangeMode: {
    type: Boolean,
    default: false,
  },
})

const emit = defineEmits(['update:modelValue'])

const quickSelectItemMap = {
  static: [
    {
      label: '今天',
      value: 'today',
    },
    {
      label: '昨天',
      value: 'yesterday',
    },
    {
      label: '明日',
      value: 'tomorrow',
    },
    {
      label: '本周一',
      value: 'monday',
    },
    {
      label: '本周末',
      value: 'sunday',
    },
    {
      label: '上周末',
      value: 'last-sunday',
    },
    {
      label: '本月第一天',
      value: 'first-day',
    },
    {
      label: '本月最后一天',
      value: 'last-day',
    },
  ],
  dynamic: [
    {
      label: '今天',
      value: 'today',
    },
    {
      label: '昨天',
      value: 'yesterday',
    },
    {
      label: '明日',
      value: 'tomorrow',
    },
  ],
  range: [
    {
      label: '今日',
      value: 'today',
    },
    {
      label: '昨日',
      value: 'yesterday',
    },
    {
      label: '本周',
      value: 'week',
    },
    {
      label: '上周',
      value: 'last-week',
    },
    {
      label: '本月',
      value: 'month',
    },
    {
      label: '上月',
      value: 'last-month',
    },
    {
      label: '本年',
      value: 'year',
    },
    {
      label: '去年',
      value: 'last-year',
    },
    {
      label: '过去 7 天',
      value: 'past-7-days',
    },
    {
      label: '过去 30 天',
      value: 'past-30-days',
    },
    {
      label: '过去 90 天',
      value: 'past-90-days',
    },
  ],
  dynamicRange: [
    {
      label: '过去 7 天',
      value: 'past-7-days',
    },
    {
      label: '过去 30 天',
      value: 'past-30-days',
    },
    {
      label: '过去 90 天',
      value: 'past-90-days',
    },
  ],
}
const popoverRef = ref(null)
const pickerPanelRef = ref(null)
const rangePickerPanelRef = ref(null)
const dynamicPanelRef = ref(null)
const dynamicRangePanelRef = ref(null)
const popoverContentRef = ref(null)
const visible = ref(false)
const dateText = ref('')
const dateValue = ref(null)
const activeName = ref('static')
const quickSelectList = computed(() => {
  return (
    statusJudgment({
      static: () => quickSelectItemMap.static,
      'static-range': () => quickSelectItemMap.range,
      dynamic: () => quickSelectItemMap.dynamic,
      'dynamic-range': () => quickSelectItemMap.dynamicRange,
    }) || []
  )
})

const onClickOutsideHandler = (event) => {
  if (popoverContentRef.value.contains(event.target)) return
  hide()
}

const show = () => {
  updateStateByModelValue()
  visible.value = true
  window.addEventListener('click', onClickOutsideHandler, true)
}

const hide = () => {
  visible.value = false
  window.removeEventListener('click', onClickOutsideHandler, true)
}

const statusJudgment = (options) => {
  if (activeName.value === 'static') {
    if (props.rangeMode) {
      return options['static-range'] && options['static-range']()
    } else {
      return options['static'] && options['static']()
    }
  } else {
    if (props.rangeMode) {
      return options['dynamic-range'] && options['dynamic-range']()
    } else {
      return options['dynamic'] && options['dynamic']()
    }
  }
}

const dataReset = () => {
  activeName.value = 'static'
  dateText.value = ''
  dateValue.value = null
  rangePickerPanelRef.value && rangePickerPanelRef.value.reset()
  pickerPanelRef.value && pickerPanelRef.value.reset()
  emit('update:modelValue', null)
}

const onInputClearHandler = () => {
  hide()
  dataReset()
}

const onInputClickHandler = () => {
  show()
}

// 静态范围快速选择处理
const staticRangeQuickSelectClick = (item) => {
  if (!rangePickerPanelRef.value) return
  switch (item.value) {
    case 'today':
      rangePickerPanelRef.value.setValue(dayjs(), dayjs())
      break
    case 'yesterday':
      rangePickerPanelRef.value.setValue(
        dayjs().subtract(1, 'day'),
        dayjs().subtract(1, 'day')
      )
      break
    case 'week':
      rangePickerPanelRef.value.setValue(
        dayjs().startOf('week'),
        dayjs().endOf('week')
      )
      break
    case 'last-week':
      rangePickerPanelRef.value.setValue(
        dayjs().subtract(1, 'week').startOf('week'),
        dayjs().subtract(1, 'week').endOf('week')
      )
      break
    case 'month':
      rangePickerPanelRef.value.setValue(
        dayjs().startOf('month'),
        dayjs().endOf('month')
      )
      break
    case 'last-month':
      rangePickerPanelRef.value.setValue(
        dayjs().subtract(1, 'month').startOf('month'),
        dayjs().subtract(1, 'month').endOf('month')
      )
      break
    case 'year':
      rangePickerPanelRef.value.setValue(
        dayjs().startOf('year'),
        dayjs().endOf('year')
      )
      break
    case 'last-year':
      rangePickerPanelRef.value.setValue(
        dayjs().subtract(1, 'year').startOf('year'),
        dayjs().subtract(1, 'year').endOf('year')
      )
      break
    case 'past-7-days':
      rangePickerPanelRef.value.setValue(dayjs().subtract(7, 'day'), dayjs())
      break
    case 'past-30-days':
      rangePickerPanelRef.value.setValue(dayjs().subtract(30, 'day'), dayjs())
      break
    case 'past-90-days':
      rangePickerPanelRef.value.setValue(dayjs().subtract(90, 'day'), dayjs())
      break
    case 'online-today':
      // todo
      break

    default:
      break
  }
}

// 静态快速选择处理
const staticQuickSelectClick = (item) => {
  if (!pickerPanelRef.value) return
  switch (item.value) {
    case 'today':
      pickerPanelRef.value.setValue(dayjs())
      break
    case 'yesterday':
      pickerPanelRef.value.setValue(dayjs().subtract(1, 'day'))
      break
    case 'tomorrow':
      pickerPanelRef.value.setValue(dayjs().add(1, 'day'))
      break
    case 'monday':
      pickerPanelRef.value.setValue(dayjs().startOf('week'))
      break
    case 'sunday':
      pickerPanelRef.value.setValue(dayjs().endOf('week'))
      break
    case 'last-sunday':
      pickerPanelRef.value.setValue(dayjs().subtract(1, 'week').endOf('week'))
      break
    case 'first-day':
      pickerPanelRef.value.setValue(dayjs().startOf('month'))
      break
    case 'last-day':
      pickerPanelRef.value.setValue(dayjs().endOf('month'))
      break

    default:
      break
  }
}

// 动态范围快速选择处理
const dynamicRangeQuickSelectClick = (item) => {
  if (!dynamicRangePanelRef.value) return
  switch (item.value) {
    case 'past-7-days':
      dynamicRangePanelRef.value.selectPastNDays(7)
      break
    case 'past-30-days':
      dynamicRangePanelRef.value.selectPastNDays(30)
      break
    case 'past-90-days':
      dynamicRangePanelRef.value.selectPastNDays(90)
      break

    default:
      break
  }
}

const dynamicQuickSelectClick = (item) => {
  if (!dynamicPanelRef.value) return
  switch (item.value) {
    case 'today':
      dynamicPanelRef.value.selectToday()
      break
    case 'yesterday':
      dynamicPanelRef.value.selectYesterday()
      break
    case 'tomorrow':
      dynamicPanelRef.value.selectTomorrow()
      break

    default:
      break
  }
}

const onQuickSelectClickHandler = (item) => {
  statusJudgment({
    static: () => staticQuickSelectClick(item),
    'static-range': () => staticRangeQuickSelectClick(item),
    dynamic: () => dynamicQuickSelectClick(item),
    'dynamic-range': () => dynamicRangeQuickSelectClick(item),
  })
  onConfirmClickHandler()
}

const staticConfirmClickHandler = () => {
  if (!pickerPanelRef.value) return
  const value = pickerPanelRef.value.getValue()
  dateText.value = value ? value.format('YYYY-MM-DD') : ''
  dateValue.value = value ? value.format('YYYY-MM-DD') : null
}

const staticRangeConfirmClickHandler = () => {
  if (!rangePickerPanelRef.value) return
  const value = rangePickerPanelRef.value.getValue()
  if (!value) {
    rangePickerPanelRef.value.reset()
    return
  }
  const start = value[0].format('YYYY-MM-DD')
  const end = value[1].format('YYYY-MM-DD')
  dateText.value = `${start} - ${end}`
  dateValue.value = [start, end]
}

const dynamicConfirmClickHandler = () => {
  if (!dynamicPanelRef.value) return
  const value = dynamicPanelRef.value.getValue()
  if (value.offset === 0) {
    dateText.value = `今天`
  } else if (value.offset > 0) {
    dateText.value = `未来 ${value.offset} 天`
  } else {
    dateText.value = `过去 ${-value.offset} 天`
  }
  dateValue.value = value
}

const dynamicRangeConfirmClickHandler = () => {
  if (!dynamicRangePanelRef.value) return
  const value = dynamicRangePanelRef.value.getValue()
  let text = ''
  const [start, end] = value
  if (typeof start === 'string') {
    text += start
  } else {
    if (start.offset === 0) {
      text += `今天`
    } else if (start.offset > 0) {
      text += `未来 ${start.offset} 天`
    } else {
      text += `过去 ${-start.offset} 天`
    }
  }
  text += ' - '
  if (end.offset === 0) {
    text += `今天`
  } else if (end.offset > 0) {
    text += `未来 ${end.offset} 天`
  } else {
    text += `过去 ${-end.offset} 天`
  }
  dateText.value = text
  dateValue.value = value
}

const onConfirmClickHandler = () => {
  statusJudgment({
    static: () => staticConfirmClickHandler(),
    'static-range': () => staticRangeConfirmClickHandler(),
    dynamic: () => dynamicConfirmClickHandler(),
    'dynamic-range': () => dynamicRangeConfirmClickHandler(),
  })
  emit('update:modelValue', dateValue.value)
  hide()
}

const updateStateByModelValue = () => {
  if (props.rangeMode) {
    if (Array.isArray(props.modelValue)) {
      const [start, end] = props.modelValue
      let text = ''
      if (
        isString(start) &&
        isString(end) &&
        dayjs(start, 'YYYY-MM-DD', true).isValid() &&
        dayjs(end, 'YYYY-MM-DD', true).isValid()
      ) {
        activeName.value = 'static'
        text = `${start} - ${end}`
      }
      if (isObject(end)) {
        activeName.value = 'dynamic'
        if (typeof start === 'string') {
          text += start
        } else {
          if (start.offset === 0) {
            text += `今天`
          } else if (start.offset > 0) {
            text += `未来 ${start.offset} 天`
          } else {
            text += `过去 ${-start.offset} 天`
          }
        }
        text += ' - '
        if (end.offset === 0) {
          text += `今天`
        } else if (end.offset > 0) {
          text += `未来 ${end.offset} 天`
        } else {
          text += `过去 ${-end.offset} 天`
        }
      }
      dateText.value = text
    }
  } else {
    if (isString(props.modelValue)) {
      if (dayjs(props.modelValue, 'YYYY-MM-DD', true).isValid()) {
        dateText.value = props.modelValue
      } else {
        dateText.value = ''
        console.warn('[cySuperDatePicker]: 日期格式不正确')
      }
    }
    if (isDate(props.modelValue)) {
      activeName.value = 'static'
      const date = dayjs(props.modelValue)
      dateText.value = date.format('YYYY-MM-DD')
    }
    if (isObject(props.modelValue) && isArray(props.modelValue) === false) {
      activeName.value = 'dynamic'
      if (props.modelValue.offset === 0) {
        dateText.value = `今天`
      } else if (props.modelValue.offset > 0) {
        dateText.value = `未来 ${props.modelValue.offset} 天`
      } else {
        dateText.value = `过去 ${-props.modelValue.offset} 天`
      }
    }
  }
  dateValue.value = props.modelValue
}

watch(
  () => props.rangeMode,
  () => {
    dataReset()
    if (popoverRef.value) {
      popoverRef.value.popperRef?.popperInstanceRef?.update()
    }
  }
)

watch(
  () => props.modelValue,
  () => {
    updateStateByModelValue()
  }
)

onMounted(() => {
  updateStateByModelValue()
})

onBeforeUnmount(() => {
  window.removeEventListener('click', onClickOutsideHandler, true)
})
</script>

<style scoped>
.super-date-picker-input {
  display: flex;
}
.popper-content {
  display: inline-flex;
  background: #ffffff;
  flex-direction: column;
  border-radius: 4px;
}
.body {
  display: flex;
  border-bottom: 1px solid #ebeef5;
}
.quick-select {
  border-right: 1px solid #ebeef5;
  flex: none;
  display: flex;
  flex-direction: column;
}
.quick-select__title {
  padding: 8px 16px;
  color: #606266;
  font-size: 14px;
  font-weight: 700;
}
.quick-select__content {
  width: 200px;
  padding: 8px;
  flex: 1;
  overflow: auto;
}
.quick-select__empty {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid #ebeef5;
  border-radius: 4px;
}
.quick-select__item {
  color: #333333;
  font-size: 12px;
  cursor: pointer;
  background: #eef4fb;
  text-align: center;
  border-radius: 4px;
  margin-bottom: 8px;
  padding: 2px 0;
}
.quick-select__item:hover {
  background: #409eff;
  color: #fff;
}
.date-panel {
  display: flex;
  flex-direction: column;
}
.date-panel__tabs {
  flex: none;
}
.date-panel__tabs :deep(.el-tabs__nav-scroll) {
  padding: 0 16px;
}
.date-panel__tabs :deep(.el-tabs__header) {
  margin: 0;
}
.date-panel__tabs-label {
  display: flex;
  align-items: center;
}
.date-panel__tabs-label-text {
  margin-right: 8px;
}
.date-panel__content {
  flex: 1;
  overflow: auto;
}
.footer {
  box-sizing: border-box;
  padding: 8px 16px;
  width: 100%;
  display: flex;
  justify-content: flex-end;
}
</style>
